#ifndef __BSP_GPIO_H
#define	__BSP_GPIO_H

#include <stdint.h>
#include <stdbool.h>

/**
 * STM32 Pin rename
 */
#define MCU_PINS \
    PA_0 = 0, PA_1, PA_2, PA_3, PA_4, PA_5, PA_6, PA_7, PA_8, PA_9, PA_10, PA_11, PA_12, PA_13, PA_14, PA_15, \
    PB_0, PB_1, PB_2, PB_3, PB_4, PB_5, PB_6, PB_7, PB_8, PB_9, PB_10, PB_11, PB_12, PB_13, PB_14, PB_15,     \
    PC_0, PC_1, PC_2, PC_3, PC_4, PC_5, PC_6, PC_7, PC_8, PC_9, PC_10, PC_11, PC_12, PC_13, PC_14, PC_15,     \
    PD_0, PD_1, PD_2, PD_3, PD_4, PD_5, PD_6, PD_7, PD_8, PD_9, PD_10, PD_11, PD_12, PD_13, PD_14, PD_15,     \
    PE_0, PE_1, PE_2, PE_3, PE_4, PE_5, PE_6, PE_7, PE_8, PE_9, PE_10, PE_11, PE_12, PE_13, PE_14, PE_15,     \
    PF_0, PF_1, PF_2, PF_3, PF_4, PF_5, PF_6, PF_7, PF_8, PF_9, PF_10, PF_11, PF_12, PF_13, PF_14, PF_15,     \
    PG_0, PG_1, PG_2, PG_3, PG_4, PG_5, PG_6, PG_7, PG_8, PG_9, PG_10, PG_11, PG_12, PG_13, PG_14, PG_15


/**
 * @brief GPIO 引脚名称
 */
typedef enum 
{
    MCU_PINS,
    
    // Not connected
    NC = (int)0xFFFFFFFF
}PinNames;

/**
 * @brief GPIO 引脚模式
 */
typedef enum
{
    PIN_INPUT = 0,      ///< 输入
    PIN_OUTPUT,         ///< 输出
    PIN_ALTERNATE_FCT,  ///< 复用
    PIN_ANALOGIC        ///< 模拟
}PinModes;

/**
 * @brief GPIO 上下拉类型
 */
typedef enum
{
    PIN_NO_PULL = 0,    ///< 无上下拉
    PIN_PULL_UP,        ///< 上拉
    PIN_PULL_DOWN       ///< 下拉
}PinTypes;

/**
 * @brief GPIO 输出配置
 */
typedef enum
{
    PIN_PUSH_PULL = 0,  ///< 推挽
    PIN_OPEN_DRAIN      ///< 开漏
}PinConfigs;

/**
 * @brief GPIO 中断触发模式
 */
typedef enum
{
    NO_IRQ = 0,         ///< 无中断
    IRQ_RISING_EDGE,    ///< 上升沿触发
    IRQ_FALLING_EDGE,   ///< 下降沿触发
    IRQ_RISING_FALLING_EDGE ///< 双边沿触发
}IrqModes;

/**
 * @brief GPIO 中断优先级
 */
typedef enum
{
    IRQ_VERY_LOW_PRIORITY = 0,
    IRQ_LOW_PRIORITY,
    IRQ_MEDIUM_PRIORITY,
    IRQ_HIGH_PRIORITY,
    IRQ_VERY_HIGH_PRIORITY
}IrqPriorities;

/**
 * @brief GPIO 中断处理函数定义
 */
typedef void( GpioIrqHandler )( uint8_t );

/**
 * @brief GPIO 对象结构体
 */
typedef struct 
{
    PinNames pin;       ///< 引脚别名（PA_0）
    uint16_t pinIndex;  ///< GPIO_Pin_0 ~ GPIO_Pin_15
#ifdef STM32F10X
    void *port;         ///< GPIOA ~ GPIOG
#elif defined GD32F10X
    uint32_t port;      ///< GPIOA ~ GPIOG
#endif
    uint16_t portIndex; ///< GPIO_PortSourceGPIOA ~ GPIO_PortSourceGPIOG
    PinModes mode;
    bool IsInitialized; ///< GPIO初始化状态
}Gpio_t;

/**
 * @brief GPIO初始化
 * @param[in]  obj          GPIO对象
 * @param[in]  pin          引脚名称
 * @param[in]  mode         工作模式 @ref PIN_INPUT @ref PIN_OUTPUT @ref PIN_ALTERNATE_FCT @ref PIN_ANALOGIC
 * @param[in]  config       输出配置 @ref PIN_PUSH_PULL @ref PIN_OPEN_DRAIN
 * @param[in]  type         输入上下拉类型 @ref PIN_NO_PULL @ref PIN_PULL_UP @ref PIN_PULL_DOWN
 * @param[in]  value        输出值(>2 不初始化值)
 * @return int8_t 
 * - @b Success : BSP_SUCCESS \n
 * - @b Fail : @ref BSP_ERROR_INVALID_PARAM - 非法入参
 */
int8_t GpioInit( Gpio_t *obj, PinNames pin, PinModes mode, PinConfigs config, PinTypes type, uint8_t value );

/**
 * @brief GPIO中断设置
 * @param[in]  obj          GPIO对象
 * @param[in]  irqMode      中断触发模式 @ref IRQ_RISING_EDGE @ref IRQ_FALLING_EDGE @ref IRQ_RISING_FALLING_EDGE
 * @param[in]  irqPriority  中断级别 @ref IrqPriorities
 * @param[in]  irqHandler   应用回调
 * @return int8_t 
 * - @b Success : BSP_SUCCESS \n
 * - @b Fail : BSP_ERROR
 */
int8_t GpioSetInterrupt( Gpio_t *obj, IrqModes irqMode, IrqPriorities irqPriority, GpioIrqHandler *irqHandler );

/**
 * @brief GPIO去中断
 * @param  obj         GPIO对象
 */
void GpioRemoveInterrupt( Gpio_t *obj );

/**
 * @brief GPIO输出
 * @param  obj          GPIO对象
 * @param  value        输出值(只能0/1 其他值写1)
 */
void GpioWrite( Gpio_t *obj, uint8_t value );

/**
 * @brief GPIO读取
 * @param  obj          GPIO对象
 * @return uint8_t 读取值(>1读取失败)
 */
uint8_t GpioRead( Gpio_t *obj );

/** GPIO翻转
 * @brief 
 * @param  obj         GPIO对象
 */
void GpioToggle( Gpio_t *obj );


#endif	/* __BSP_GPIO_H */

